import os
import json
import time

# from django.core.paginator import Paginator  # 注释掉Django分页器
from datetime import datetime
import dofile
from flask import Blueprint, request, render_template, jsonify, session, flash, redirect
from werkzeug.utils import secure_filename
import math

import verfy
from models import Homework, Uploadhomework, Teacher, Student,Copy
from collections import OrderedDict
from exts import db
import plagiaris_check as pc


from Utils.paginator import SimplePaginator

bp = Blueprint("homework", __name__, url_prefix="/homework")

ALLOWED_EXTENSIONS = set(['jpg', 'txt', 'pdf', 'doc', 'docx'])  # 限制上传文件格式


def allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


def _is_valid_c_code(code):
    """检查代码是否为有效的C语言代码格式"""
    if not code or not code.strip():
        return False
    
    code = code.strip()
    
    # 基本的C语言代码特征检查
    c_indicators = [
        '#include',  # 头文件包含
        'int main',  # main函数
        'void main', # void main函数
        'printf',    # 输出函数
        'scanf',     # 输入函数
        'return',    # 返回语句
    ]
    
    # 必须包含main函数
    if 'main' not in code:
        return False
    
    # 必须包含大括号
    if '{' not in code or '}' not in code:
        return False
    
    # 检查是否包含C语言的基本特征
    has_c_features = any(indicator in code for indicator in c_indicators)
    
    # 检查是否包含明显的非C语言特征
    non_c_indicators = [
        'def ',      # Python函数定义
        'function',  # JavaScript函数
        'class ',    # 类定义（Java/Python等）
        'public class', # Java类
        'import ',   # Python/Java导入
        'console.log', # JavaScript输出
        'System.out.println', # Java输出
        'print(',    # Python输出
        '<?php',     # PHP标签
        '<html',     # HTML标签
        '<script',   # JavaScript标签
    ]
    
    has_non_c_features = any(indicator in code for indicator in non_c_indicators)
    
    # 如果包含非C语言特征，则认为不是C代码
    if has_non_c_features:
        return False
    
    # 如果包含C语言特征，则认为是C代码
    return has_c_features


@bp.before_request
def before_request():
    """作业蓝图权限检查"""
    # 检查用户是否登录
    if session.get('is_login') != 'true':
        # 对于API请求返回JSON错误
        if request.is_json or request.path.endswith('.json') or 'list1' in request.path:
            return jsonify({'error': '请先登录'}), 401
        else:
            return redirect('/login')
    
    # 获取当前请求的路径
    current_path = request.path
    user_role = session.get('role')
    
    # 首先检查用户角色是否有效
    if user_role not in ['teacher', 'student']:
        return jsonify({'error': f'用户角色无效: {user_role}'}), 403
    
    # 精确路由权限控制
    # 学生和教师都可以访问的路由
    if (current_path == '/homework/' or 
        current_path == '/homework/student/list' or 
        current_path == '/homework/submit' or 
        current_path == '/homework/list1' or
        current_path.startswith('/homework/list1?') or
        current_path.startswith('/homework/view_text_homework/') or
        current_path == '/homework/load'):
        # 通用路由，允许访问
        pass
    # 教师专用路由
    elif (current_path == '/homework/list' or 
          current_path.startswith('/homework/save') or 
          current_path.startswith('/homework/update') or
          current_path.startswith('/homework/delete') or
          current_path == '/homework/example'):
        # 教师专用路由，只允许教师访问
        if user_role != 'teacher':
            return jsonify({'error': '权限不足，仅教师可以访问此功能'}), 403
    else:
        # 未定义的路由，拒绝访问
        return jsonify({'error': '未授权的访问路径'}), 403


@bp.route("/")
def student_index():
    return "这是作业界面"


@bp.route("/example", methods=["POST"])
def homework_example():  # put application's code here
    # 再sallist中修改name的信息
    data = request.json
    print(data.get("inputStr1"))
    str1 = "inputStr"
    str2 = "outputStr"
    input_path = 'input.txt'
    output_path = 'output.txt'

    base_path = "homework_uploads/"
    path1 = str(data.get("ID")) + "-" + data.get("title")
    example_path = base_path + path1
    f1 = open(example_path + "/" + input_path, 'w', encoding='utf-8')
    f2 = open(example_path + "/" + output_path, 'w', encoding='utf-8')
    i = 1
    while i < 7:
        inputStr = data.get(str1 + str(i))
        outputStr = data.get(str2 + str(i))
        # 如果输入和输出都为空，则停止处理
        if len(inputStr) == 0 and len(outputStr) == 0:
            break
        # 前台获得的用例数据
        print(inputStr)
        print(outputStr)
        # 只有当输入不为空时才写入输入文件
        if len(inputStr) > 0:
            f1.write(inputStr + "\n---\n")
        f2.write(outputStr + "\n---\n")
        i += 1
    f1.close()
    f2.close()
    data = {'code': 0, 'msg': "成功"}
    return json.dumps(data)


def get_user_id():
    return session.get("user_id")


@bp.route("/list1", methods=["GET"])
def homework_list1():
    """获取作业列表数据（支持分页）"""
    try:
        ID = request.args.get("ID")
        pageIndex = request.args.get("pageIndex", 1)
        pageSize = request.args.get("pageSize", 10)
        
        # 查询作业数据
        if ID is not None and ID.strip():
            homeworks = Homework.query.filter_by(ID=ID).all()
        else:
            homeworks = Homework.query.all()
        
        # 转换为JSON格式
        data = []
        for homework in homeworks:
            try:
                data.append(homework.to_json())
            except Exception as e:
                print(f"作业数据转换错误: {str(e)}")
                continue
        
        total_count = len(data)
        
        # 使用自定义分页器
        if pageSize and int(pageSize) > 0:
            paginator = SimplePaginator(data, pageSize)
            page_data = paginator.page(pageIndex)
        else:
            page_data = data
        
        return OrderedDict(code=0, count=total_count, data=page_data)
        
    except Exception as e:
        print(f"获取作业列表错误: {str(e)}")
        return OrderedDict(code=1, msg=f"获取作业列表失败: {str(e)}", count=0, data=[])


@bp.route("/list")
def homework_list():
    print("作业列表")
    # 1。get查找 根据主键查找
    # teacher = Teacher.query.get(1001)
    # print(teacher.name)
    # 2。fliter_by查找
    # students = Student.query.filter_by(class_id = "230101")
    return render_template('homework.html')


@bp.route("/student/list")
def student_homework_list():
    print("作业列表")
    # 1。get查找 根据主键查找
    # teacher = Teacher.query.get(1001)
    # print(teacher.name)
    # 2。fliter_by查找
    # students = Student.query.filter_by(class_id = "230101")
    return render_template('student_homework.html')

@bp.route("/debug")
def debug_submission():
    """调试提交功能的页面"""
    return render_template('debug_frontend_issue.html')


@bp.route('/delete/<ids>', methods=["GET"])
def homework_delete(ids):  # put application's code here
    # 删除作业及其关联数据
    try:
        # 验证作业ID
        if not ids:
            return jsonify({'code': 1, 'msg': "作业ID不能为空"})
            
        try:
            homework_id = int(ids)
        except (ValueError, TypeError):
            return jsonify({'code': 1, 'msg': "作业ID格式无效"})
            
        # 查找作业
        homework = Homework.query.filter_by(ID=homework_id).first()
        if not homework:
            return jsonify({'code': 1, 'msg': "作业不存在"})
        
        # 删除相关的爱国情感分析记录
        from models import PatrioticAnalysis
        upload_homeworks = Uploadhomework.query.filter_by(hnumber=homework_id).all()
        for upload_homework in upload_homeworks:
            # 删除爱国情感分析记录
            patriotic_analyses = PatrioticAnalysis.query.filter_by(upload_homework_id=upload_homework.ID).all()
            for analysis in patriotic_analyses:
                db.session.delete(analysis)
        
        # 删除作业提交记录
        for up in upload_homeworks:
            db.session.delete(up)
            
        # 删除查重记录
        copys = Copy.query.filter_by(hid=homework_id).all()
        for cp1 in copys:
            db.session.delete(cp1)
            
        # 删除查重版本记录
        from models import Copyversion
        copyversions = Copyversion.query.filter_by(hid=homework_id).all()
        for cv in copyversions:
            db.session.delete(cv)
        
        # 最后删除作业本身
        db.session.delete(homework)
        db.session.commit()
        
        return jsonify({'code': 0, 'msg': "删除成功"})
        
    except Exception as e:
        db.session.rollback()
        print(f"删除作业错误: {e}")
        return jsonify({'code': 1, 'msg': f"删除失败: {str(e)}"})


@bp.route('/submit', methods=['GET', 'POST'])
def homework_submit():  # put application's code here
    # 学生作业提交处理（支持代码和文本作业）
    time_str1 = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
    print(f"=== 作业提交开始 ===")
    print(f"请求方法: {request.method}")
    print(f"请求路径: {request.path}")
    print(f"Content-Type: {request.content_type}")
    
    if request.method == 'POST':
        try:
            print(f"请求原始数据: {request.get_data()}")
            data = request.json
            print(f"解析后的JSON数据: {data}")
            if not data:
                print("错误: 请求数据为空")
                return json.dumps({'code': 1, 'msg': "无效的请求数据"})
            
            # 检查必要的session数据
            user_id = session.get('user_id')
            class_id2 = session.get('class_id2')
            if not user_id or not class_id2:
                return json.dumps({'code': 1, 'msg': "用户session信息不完整，请重新登录"})
            
            # 验证作业ID
            homework_id = data.get("ID")
            if not homework_id:
                return json.dumps({'code': 1, 'msg': "缺少作业ID"})
                
            try:
                homework_id = int(homework_id)
            except (ValueError, TypeError):
                return json.dumps({'code': 1, 'msg': "作业ID格式无效"})
                
            homework = Homework.query.filter_by(ID=homework_id).first()
            if not homework:
                return json.dumps({'code': 1, 'msg': "作业不存在"})
                
            time_str2 = homework.deadline
            time_format = "%Y-%m-%d %H:%M:%S"
            time1 = datetime.strptime(time_str1, time_format)
            time2 = datetime.strptime(time_str2, time_format)
            print(f"提交时间: {time1}, 截止时间: {time2}")
            
            if time1 > time2:
                return json.dumps({'code': 2, 'msg': "作业已截止"})
            
            # 获取提交类型（从前端传来）
            submission_type = data.get("submission_type", homework.homework_type)
            
            # 验证提交内容
            if submission_type == 'text':
                # 文本作业验证
                text_content = data.get("text_content")
                if not text_content or not text_content.strip():
                    return json.dumps({'code': 1, 'msg': "请输入文本作业内容"})
                
                # 文本内容长度限制
                text_content = text_content.strip()
                if len(text_content) > 50000:  # 限制最大50000字符
                    return json.dumps({'code': 1, 'msg': "文本内容过长，请控制在50000字符以内"})
                
                if len(text_content) < 10:  # 最小10字符
                    return json.dumps({'code': 1, 'msg': "文本内容过短，至少需要10个字符"})
                
                # 处理文本作业提交
                real = Uploadhomework.query.filter_by(sid=user_id, hnumber=homework_id).first()
                
                if real:
                    # 更新现有记录
                    real.frequency = real.frequency + 1
                    real.htime = str(time1)
                    real.text_content = text_content
                    real.submission_type = 'text'
                    real.homeworkpath = None  # 文本作业无文件路径
                    real.grade = None  # 等待评分
                    db.session.commit()
                    return json.dumps({'code': 0, 'msg': "文本作业提交成功！请等待管理员评分"})
                else:
                    # 创建新记录
                    uploadhomework = Uploadhomework(
                        sid=user_id,
                        hnumber=homework_id,  # 使用验证后的homework_id
                        text_content=text_content,
                        submission_type='text',
                        homeworkpath=None,  # 文本作业无文件路径
                        htime=str(time1), 
                        frequency=1, 
                        grade=None  # 等待管理员评分
                    )
                    db.session.add(uploadhomework)
                    db.session.commit()
                    return json.dumps({'code': 0, 'msg': "文本作业提交成功！请等待管理员评分"})
            
            else:
                # 代码作业验证和处理（原有逻辑）
                if not data.get("code"):
                    return json.dumps({'code': 1, 'msg': "请输入作业代码"})
                
                base_path = "homework_uploads/"
                path1 = str(homework_id) + "-" + data.get("title")  # 3001-第一次作业
                student_path = base_path + path1  # homework_uploads/3001-第一次作业
                path = student_path + "/"  # homework_uploads/3001-第一次作业/
                file_name = "class" + str(class_id2)
                
                # 确保目录存在
                if not os.path.exists(base_path):
                    os.makedirs(base_path)
                if path1 not in os.listdir(base_path):
                    os.mkdir(student_path)
                if file_name not in os.listdir(path):
                    os.mkdir(path + file_name)
                    
                files = str(user_id) + ".c"
                full_path = os.path.join(path, file_name, files)
                full_path = full_path.replace("\\", '/')
                
                # 检查代码格式是否为C语言
                code_content = data.get("code").strip()
                if not _is_valid_c_code(code_content):
                    return json.dumps({'code': 1, 'msg': "格式错误，请输入C语言代码！"})
                
                # 保存代码文件
                dofile.write_code(full_path, code_content)
                
                # 编译代码
                result = dofile.is_right(full_path, class_id2, user_id)
                
                if result[0]:
                    # 编译成功，保存提交记录并尝试自动评分
                    real = Uploadhomework.query.filter_by(sid=user_id, hnumber=homework_id).first()
                    
                    if real:
                        # 更新现有记录
                        real.frequency = real.frequency + 1
                        real.htime = str(time1)
                        real.homeworkpath = full_path
                        real.submission_type = 'code'
                        real.text_content = None  # 代码作业无文本内容
                        real.grade = None  # 等待评分
                        db.session.commit()
                        return json.dumps({'code': 0, 'msg': "代码作业提交成功！等待评分"})
                    else:
                        # 创建新记录
                        uploadhomework = Uploadhomework(
                            sid=user_id,
                            hnumber=homework_id,  # 使用验证后的homework_id
                            homeworkpath=full_path,
                            submission_type='code',
                            text_content=None,  # 代码作业无文本内容
                            htime=str(time1), 
                            frequency=1, 
                            grade=None  # 等待评分
                        )
                        db.session.add(uploadhomework)
                        db.session.commit()
                        return json.dumps({'code': 0, 'msg': "代码作业提交成功！等待评分"})
                else:
                    if os.path.exists(full_path):
                        os.remove(full_path)
                    return json.dumps({'code': 1, 'msg': result[1]})
                
        except Exception as e:
            print(f"作业提交错误: {str(e)}")
            import traceback
            traceback.print_exc()  # 打印详细的错误堆栈
            return json.dumps({'code': 1, 'msg': f"提交失败: {str(e)}"})
            
    return json.dumps({'code': 1, 'msg': "请求方法错误"})




def get_new_upload_id():
    """获取新的上传作业ID"""
    try:
        # 获取最大的ID值
        max_id_result = db.session.query(db.func.max(Uploadhomework.ID)).scalar()
        if max_id_result is None:
            return 1  # 如果没有记录，从1开始
        return max_id_result + 1
    except Exception as e:
        print(f"获取新ID时出错: {e}")
        # 备用方案：查询所有记录
        uploadhomeworks = Uploadhomework.query.all()
        if not uploadhomeworks:
            return 1
        max_id = max(uploadhomework.ID for uploadhomework in uploadhomeworks)
        return max_id + 1


@bp.route('/save', methods=['GET', 'POST'])
def homework_save():  # put application's code here
    # 再sallist中修改name的信息
    time1 = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
    if request.method == 'POST':
        print(request.files)
        data = request.form.get("postData")
        data = json.loads(data)
        
        # 数据验证
        homework_id = data.get("ID")
        title = data.get("title")
        h_content = data.get("h_content")
        homework_type = data.get("homework_type", "code")
        
        if not homework_id:
            return json.dumps({'code': 1, 'msg': "作业ID不能为空"})
        if not title or not title.strip():
            return json.dumps({'code': 1, 'msg': "作业标题不能为空"})
        if not h_content or not h_content.strip():
            return json.dumps({'code': 1, 'msg': "作业内容不能为空"})
        if homework_type not in ['code', 'text']:
            return json.dumps({'code': 1, 'msg': "作业类型无效"})
            
        # 检查作业ID是否已存在
        existing_homework = Homework.query.filter_by(ID=homework_id).first()
        if existing_homework:
            return json.dumps({'code': 1, 'msg': "作业ID已存在，请使用其他ID"})
        
        print(data.get("ID"))
        deadline = str(data.get("deadline")).replace('T', ' ')
        deadline = deadline+":59"
        # check if the post request has the file part
        if len(request.files) == 0:
            path = "homework_uploads/"
            file_name = os.path.join(data.get("ID") + "-" + data.get("title"))
            if file_name not in os.listdir(path):
                os.mkdir(path + file_name)
            homework = Homework(ID=data.get("ID"), tid=session.get('user_id'), title=data.get("title"),
                                h_content=data.get("h_content"),
                                homework_type=data.get("homework_type", "code"),  # 新增作业类型字段
                                issuedate=time1, deadline=deadline,
                                submit_limit=data.get("submit_limit"), attachment_path=path + file_name,
                                attachment_name="", answer=data.get("answer"))
            db.session.add(homework)
            db.session.commit()
            data = {'code': 0, 'msg': "成功"}
            return json.dumps(data)
        else:
            file = request.files['file']
            print(file)
            if file:
                if allowed_file(file.filename):
                    if file.filename == '':
                        flash('No selected file')
                        return redirect(request.url)
                    filename = secure_filename(file.filename).split('.')
                    filetype = filename[len(filename) - 1]
                    path = "homework_uploads/"
                    file_name = data.get("ID") + "-" + data.get("title")
                    dir_name = path + file_name
                    if file_name not in os.listdir(path):
                        os.mkdir(dir_name)
                    filename = "附件." + str(filetype)

                    file.save(dir_name + '/' + filename)
                    homework = Homework(ID=data.get("ID"), tid=session.get('user_id'), title=data.get("title"),
                                        h_content=data.get("h_content"),
                                        homework_type=data.get("homework_type", "code"),  # 新增作业类型字段
                                        issuedate=time1, deadline=deadline,
                                        submit_limit=data.get("submit_limit"), attachment_path=dir_name,
                                        attachment_name=filename, answer=data.get("answer"))
                    db.session.add(homework)
                    db.session.commit()
                    data = {'code': 0, 'msg': "成功"}
                    return json.dumps(data)

    return json.dumps({'code': 1, 'msg': "成功"})


@bp.route('/update', methods=['GET', 'POST'])
def homework_edited():  # put application's code here
    # 再sallist中修改name的信息
    if request.method == 'POST':
        data = request.form.get("postData")
        data = json.loads(data)
        homework = Homework.query.filter_by(ID=data.get("ID")).first()
        homework.tid = data.get("tid")
        homework.title = data.get("title")
        homework.h_content = data.get("h_content")
        homework.homework_type = data.get("homework_type", homework.homework_type)  # 更新作业类型
        homework.issuedate = data.get("issuedate")
        homework.deadline = str(data.get("deadline")).replace("T", " ")+":59"
        homework.submit_limit = data.get("submit_limit")
        homework.attachment_path = data.get("attachment_path")
        homework.attachment_name = data.get("attachment_name")
        homework.answer = data.get("answer")
        db.session.commit()
        data = {'code': 0, 'msg': "成功"}
        return json.dumps(data)
    return json.dumps({'code': 1, 'msg': "成功"})


@bp.route('/check_plagiarism', methods=['POST'])
def check_plagiarism():
    print("检测抄袭")
    data = request.get_json()
    dir_temp = data.get('dir')

    if dir_temp:
        # 调用 program.py 中的 plagiaris_check 函数
        result = pc.plagiaris_check(dir_temp)
        return jsonify({"result": result})
    else:
        return jsonify({"error": "Invalid data."})


@bp.route('/view_text_homework/<int:upload_id>', methods=['GET'])
def view_text_homework(upload_id):
    """查看文本作业内容"""
    try:
        upload_homework = Uploadhomework.query.get(upload_id)
        if not upload_homework:
            return jsonify({"code": 1, "message": "作业提交记录不存在"})
        
        if upload_homework.submission_type != 'text':
            return jsonify({"code": 1, "message": "该作业不是文本类型"})
        
        return jsonify({
            "code": 0, 
            "data": {
                "text_content": upload_homework.text_content,
                "student_name": upload_homework.student.name,
                "student_id": upload_homework.sid,
                "submit_time": upload_homework.htime,
                "homework_title": upload_homework.homework.title
            }
        })
    except Exception as e:
        print(f"查看文本作业错误: {str(e)}")
        return jsonify({"code": 1, "message": f"查看失败: {str(e)}"})

@bp.route('/your_get_homework_url/<int:homework_id>', methods=['GET'])
def get_homework(homework_id):
    # 查询数据库获取作业信息
    homework = Homework.query.get(homework_id)
    if homework:
        # 如果找到了作业信息

        attachment_path = homework.attachment_path  # 假设附件路径存储在 attachment_path 列中
        print("123")
        print(attachment_path)
        pc.plagiaris_check(attachment_path, homework_id)
        return jsonify({"code": 0, "data": {"attachment_path": attachment_path}})
    else:
        # 如果未找到作业信息
        return jsonify({"code": 1, "message": "Homework not found"})
